|
Technote 1118Unlocking |
CONTENTS |
Recently, Apple became aware of problems in Mac OS and in third-party code which can cause a crash. The problem occurs when a program inadvertently unlocks one or more QuickDraw data structures. The crash typically occurs elsewhere, when the system accesses one of these data structures under the assumption that it is locked. This Technote is addressed to two audiences: developers
whose products make any use of the |
The SymptomsThe problem manifests most often as a crash in It should be noted that a crash could theoretically appear in a
number of places as a result of the problem. The problem generally
does not occur near the site of the crash. One of the more insidious
potential examples of this is in the cursor drawing routines, which
are executed at interrupt time. An unlocked |
The Problem
|
// begin problematic code GDHandle gdh = GetMainDevice ( ); HLock ((Handle)gdh); // do something with or to gdh // which moves memory (requires gdh to be locked) HUnlock ((Handle)gdh); // this is the problem line // end problematic code |
The above code assumes that the
|
Notes: Versions of Monitors & Sound which shipped in Mac OS 8.1 and later do not have this problem. There has always been a requirement that a Thus, the potential for the problem has always been present, though the symptoms have only recently been isolated. Because of the complex way in which relocatable Memory Manager blocks move over time, programs which cause the problem have not necessarily also caused the symptoms, and when they have caused the symptoms, the symptoms have not always been easily reproducible. (The offending programs have been "getting away with it.") An exhaustive search of Apple's previous documentation
turned up no instances of explicit prohibitions against
unlocking a |
The SolutionsThe previous version of this Technote claimed there would be a solution which users could apply. In fact, there is only a developer solution. |
Developer SolutionYou should make sure none of your code unlocks a |
GDHandle gdh = GetMainDevice ( ); SInt8 hState = HGetState ((Handle) gdh); HLock ((Handle)gdh); // do something with or to gdh // which moves memory (requires gdh to be locked) HSetState ((Handle)gdh,hState); |
This code saves the handle's state, locks the handle, and restores the handle's previous state. This means that if the handle is locked before this code runs, it will stay locked afterward, and if the handle is unlocked before this code runs, it will be unlocked afterward. In a perfect world, you would not need to lock or unlock any
Another technique would be to avoid locking a Apple has not found any cases in which you need to keep any
If your program needs to lock any
|